package org.xqh.test.ugreen;

import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.codec.digest.DigestUtils;
import org.springframework.util.StringUtils;
import org.xqh.test.ugreen.apitest.RedisOptTest;

import java.nio.charset.Charset;
import java.nio.charset.StandardCharsets;
import java.text.MessageFormat;
import java.util.*;

/**
 * @ClassName CertificateUtils
 * @Description 接口签名校验 逻辑
 * @Author xuqianghui
 * @Date 2021/12/29 17:03
 * @Version 1.0
 */
@Slf4j
public class CertificateUtils {

    private final static Charset CHARSET = StandardCharsets.UTF_8;

    public static <T> String createSignForCloud2(final Map<String, Object> params, String secretKey) {
        //1、除去空值请求参数
        HashMap<String, String> newRequestParams = removeEmptyParam(params);


        //移除签名 sign
        if(newRequestParams.containsKey(RedisOptTest.REQUEST_HEAD_SIGN)){
            newRequestParams.remove(RedisOptTest.REQUEST_HEAD_SIGN);
        }

        //移除接入类型accessType
        if(newRequestParams.containsKey(RedisOptTest.REQUEST_HEAD_ACCESS_TYPE)){
            newRequestParams.remove(RedisOptTest.REQUEST_HEAD_ACCESS_TYPE);
        }

        String strUrlParams = parseUrlString(newRequestParams);

        //4、最后拼接上secretKey得到字符串stringSignTemp
        String stringSignTemp = MessageFormat.format("{0}&SecretKey={1}", strUrlParams, secretKey);
        //5、对stringSignTemp进行MD5运算，得到sign值
        String signRet = DigestUtils.md5Hex(stringSignTemp.getBytes(CHARSET));
        log.info("sign-check-v2-{}. calc-sign-string: {}, md5-result:{}", newRequestParams.getOrDefault(RedisOptTest.REQUEST_HEAD_ACCESS_KEY, "access-key"), stringSignTemp, signRet);
        return signRet;
    }

    public static <T> String createSignForCloud(final Map<String, Object> params, String secretKey) {
        //1、除去空值请求参数
        HashMap<String, String> newRequestParams = removeEmptyParam(params);


        //移除签名 sign
        if(newRequestParams.containsKey(RedisOptTest.REQUEST_HEAD_SIGN)){
            newRequestParams.remove(RedisOptTest.REQUEST_HEAD_SIGN);
        }

        //移除接入类型accessType
        if(newRequestParams.containsKey(RedisOptTest.REQUEST_HEAD_ACCESS_TYPE)){
            newRequestParams.remove(RedisOptTest.REQUEST_HEAD_ACCESS_TYPE);
        }

        String strUrlParams = parseUrlString(newRequestParams);

        //4、最后拼接上secretKey得到字符串stringSignTemp
        String stringSignTemp = MessageFormat.format("{0}&SecretKey={1}", strUrlParams, secretKey);
        //5、对stringSignTemp进行MD5运算，得到sign值
        String signRet = DigestUtils.md5Hex(stringSignTemp.getBytes(CHARSET));
        log.info("sign-check-v2-{}. calc-sign-string: {}, md5-result:{}", newRequestParams.getOrDefault(RedisOptTest.REQUEST_HEAD_ACCESS_KEY, "access-key"), stringSignTemp, signRet);
        return signRet;
    }

    /**
     *
     * @param params
     * @param secretKey
     * @param <T>
     * @return
     */
    public static <T> String createSignNew(final Map<String, Object> params, String secretKey) {
        //1、除去空值请求参数
        HashMap<String, String> newRequestParams = removeEmptyParam(params);


        //移除签名 sign
        if(newRequestParams.containsKey(RedisOptTest.REQUEST_HEAD_SIGN)){
            newRequestParams.remove(RedisOptTest.REQUEST_HEAD_SIGN);
        }

        //移除接入类型accessType
        if(newRequestParams.containsKey(RedisOptTest.REQUEST_HEAD_ACCESS_TYPE)){
            newRequestParams.remove(RedisOptTest.REQUEST_HEAD_ACCESS_TYPE);
        }

        String strUrlParams = parseUrlString(newRequestParams);

        //4、最后拼接上secretKey得到字符串stringSignTemp
        String stringSignTemp = MessageFormat.format("{0}&SecretKey={1}", strUrlParams, secretKey);
        //5、对stringSignTemp进行MD5运算，得到sign值
        String signRet = DigestUtils.md5Hex(stringSignTemp.getBytes(CHARSET));
        log.info("sign-check-v2-{}. calc-sign-string: {}, md5-result:{}", newRequestParams.getOrDefault(RedisOptTest.REQUEST_HEAD_ACCESS_KEY, "access-key"), stringSignTemp, signRet);
        return signRet;
    }

    /**
     * 移除空请求参数
     */
    private static HashMap<String, String> removeEmptyParam(final Map<String, Object> params) {
        HashMap<String, String> newParams = new HashMap<>(10);
        if (params == null || params.size() <= 0) {
            return newParams;
        }
        for (String key : params.keySet()) {
            if(params.get(key) instanceof JSONObject || params.get(key) instanceof JSONArray){
                //值 为对象/数组 的 参数 不处理
                continue;
            }
            String value = String.valueOf(params.get(key));
            if(StringUtils.isEmpty(value)){
                continue;
            }
            newParams.put(key, value);
        }
        return newParams;
    }

    /**
     * 使用URL键值对的格式（即key1=value1&key2=value2…）将参数列表拼接成字符串
     */
    private static String parseUrlString(final HashMap<String, String> requestMap) {
        List<String> keyList = new ArrayList<>(requestMap.keySet());
        Collections.sort(keyList);

        List<String> entryList = new ArrayList<>();
        for (String key : keyList) {
            String value = requestMap.get(key);
            entryList.add(MessageFormat.format("{0}={1}", key, value));
        }
        return String.join("&", entryList);
    }
}
